Java JavaScript Python C# C C++ Go Kotlin PHP Swift R Ruby TypeScript Scala SQL Perl rust VisualBasic Matlab Julia

Generics → Upper Bounded Wildcards

Generics

Upper Bounded Wildcards

In Java, wildcards are used with generics to increase flexibility when working with collections. Upper bounded wildcards, denoted by `<? extends T>`, specify that a generic type parameter can be of type `T` or any subtype of `T`. This means you can use methods that operate on the common features of `T` and its subtypes without needing to know the exact type at compile time.

Scenario: Processing a list of Numbers

Suppose you have a method that calculates the sum of numbers in a list:
Java public static double sum(List<? extends Number> numbers) { double sum = 0; for (Number number : numbers) { sum += number.doubleValue(); } return sum; }
Notice `List<? extends Number>`. This means the `numbers` list can contain `Number` objects or any subclass of `Number` (like `Integer`, `Double`, `Float`, etc.). The method can safely access the `doubleValue()` method because it's guaranteed to be present in all subclasses of `Number`.
Java upper bounded wildcards example import java.util.*; public class Main{ public static double sum(List<? extends Number> numbers) { double sum = 0; for (Number number : numbers) { sum += number.doubleValue(); } return sum; } public static void main(String[] args) { List<Integer> ints = List.of(1, 2, 3, 4, 5); List<Double> doubles = List.of(1.1, 2.2, 3.3); System.out.println("Sum of integers: " + sum(ints)); System.out.println("Sum of doubles: " + sum(doubles)); } }

Output

Sum of integers: 15.0 Sum of doubles: 6.6
This works because both `List<Integer>` and `List<Double>` are considered subtypes of `List<? extends Number>`.

Why not `List<Number>`?

You might think using `List<Number>` would be simpler. However, that would restrict the method to *only* lists of `Number` objects, excluding lists of subclasses. The upper bounded wildcard offers more flexibility.

Limitations: Adding elements

A crucial restriction with upper bounded wildcards is that you cannot add elements to a list with this type of wildcard.
Adding elements will show error List<? extends Number> numbers = List.of(1, 2, 3); numbers.add(4); // Compile-time error!
This fails because the compiler doesn't know the exact type within the list. Adding an `Integer` might be fine, but what if the list is actually a `List<Byte>`? The `add()` method would then cause a runtime exception. To avoid this potential runtime error, the compiler simply prevents adding any elements.
Contrast with Unbounded Wildcards An unbounded wildcard (`<?>`) is even more flexible; it accepts lists of *any* type. However, you have even fewer operations available. You can only call methods defined in the `Object` class (e.g., `size()`, `isEmpty()`, `get()`). You cannot call methods specific to a particular type or its subtypes. In Summary Upper bounded wildcards provide a balance between flexibility and type safety. They allow you to work with collections of various related types without sacrificing compile-time safety, but with the trade-off of being unable to add elements to the list. Choose them when you need to read from a list containing objects of various subtypes of a common supertype, but not modify the list's contents. If you need to add elements, you'll need a specific generic type or an unbounded wildcard (with even more limitations).

Tutorials